package org.rslai.socket.testtool.util;

import java.io.IOException;
import java.io.StringReader;

/**
 * 不同类型字符串转换操作
 * @author rslai
 *
 */
public class TranHandle {

	/**
	 * 将int型的转为指定长度，指定格式的，倒叙的Hex字符串。例如：十进制的291，转为十六进制后为123，但这个方法会转换为"^23^01"
	 * @param i 需要转换的int数
	 * @param prefixStr 添加在Hex字符前边的内容，例如：十进制的84，转为十六进制后为54，如果你想返回的字符串为"^54",就把这个参数设置为"^"
	 * @param lenght 转换后生成几组Hex字符，例如：十进制的84，转为十六进制后为"^54"，如果把这个参数设置为2，那转换后将为"^54^00"
	 * @return 返回的Hex字符串
	 */
	public static String intToReverseHexStr(int i, String prefixStr, int lenght) {
		StringBuffer rStr = new StringBuffer();

		for (int j=0; j<lenght; j++) {
			String tmp = java.lang.Integer.toHexString(i & 0xff);
			if (tmp.length() == 1) {
				rStr.append(prefixStr + "0" + tmp);
			} else {
				rStr.append(prefixStr + tmp);
			}
			i = i >> 8;
		}

		return rStr.toString();
	}

	/**
	 * 将16进制的字符转换为10进制数，例如：A 返回 10
	 * @param chr 待转字符
	 * @return 返回10进制数
	 */
	private static int hexCharToDec(int chr) {
		return hexCharToDec((char) chr);
	}

	/**
	 * 将16进制的字符转换为10进制数，例如：A 返回 10
	 * @param chr 待转字符
	 * @return 返回10进制数
	 */
	private static int hexCharToDec(char chr) {
		int tmp;

		switch(chr) {
			// 0 - 9
			case '0':
				tmp = 0;
				break;
			case '1':
				tmp = 1;
				break;
			case '2':
				tmp = 2;
				break;
			case '3':
				tmp = 3;
				break;
			case '4':
				tmp = 4;
				break;
			case '5':
				tmp = 5;
				break;
			case '6':
				tmp = 6;
				break;
			case '7':
				tmp = 7;
				break;
			case '8':
				tmp = 8;
				break;
			case '9':
				tmp = 9;
				break;

			// A - F
			case 'A':
				tmp = 10;
				break;
			case 'B':
				tmp = 11;
				break;
			case 'C':
				tmp = 12;
				break;
			case 'D':
				tmp = 13;
				break;
			case 'E':
				tmp = 14;
				break;
			case 'F':
				tmp = 15;
				break;

			// a - f
			case 'a':
				tmp = 10;
				break;
			case 'b':
				tmp = 11;
				break;
			case 'c':
				tmp = 12;
				break;
			case 'd':
				tmp = 13;
				break;
			case 'e':
				tmp = 14;
				break;
			case 'f':
				tmp = 15;
				break;

			default:
				tmp = 0;
				break;
		}

		return tmp;
	}

	/**
	 * 将字符串转为byte数组，例如：将 .NET^01^00^00^00^00^00^F9^07 转为{'.', 'N', 'E', 'T', (byte)(0x01), (byte)(0x00) ......}
	 * @param str 输入的字符串
	 * @return 返回的byte数组
	 */
	public static byte[] strToArrayByte(String str) {
		int strLen = str.length(); // 待处理字符串长度
		byte tmpBytes[] = new byte[strLen]; // 临时保存的字节数组

		int factLen = 0; // 转换后的字符串长度
		
		StringReader strRead = new StringReader(str);
		try {
			while(true){
				byte tmp = (byte)strRead.read();

				// 字符串读取到最后退出循环
				if (tmp == -1) {
					break;
				}

				if (tmp == '^'){
					// 当读到 ^ 字符时将其后边的两个16进制字符转为一个字符，存入byte数组
					tmpBytes[factLen] = ((byte) ( (hexCharToDec(strRead.read()) << 4) + hexCharToDec(strRead.read())));
				} else {
					// 没读到 ^ 字符直接存入byte数组
					tmpBytes[factLen] = tmp;
				}

				factLen ++;
			}
		} catch (IOException e) {
		    e.printStackTrace();
		}

		// 去掉多余byte，生成最后的byte数组
		byte finallyBytes[] = new byte[factLen]; // 保存最后由字符串转换的byte数组
		System.arraycopy(tmpBytes, 0, finallyBytes, 0, factLen);

		return finallyBytes;
	}

	/**
	 * 将hex字符串转为字符串，编程阶段使用的函数。例如：^2E^4E^45^54^01^00^00^00^00^00^F9^07 转为 .NET^01^00^00^00^00^00^F9^07
	 * 可能一下字符被误转换，一般在几个16进制字符中夹杂一下字符一般为误转换：
	 * 		\r ^0D
	 * 		\n ^0A
	 * 		) ^29
	 * @param lineLen 每行输出的长度
	 * @param prefixStr 前缀字符（在前面打印的内容）
	 * @param str 输入的hex字符串
	 */
	public static void hexStrToStr(int lineLen, String prefixStr, String str) {
		StringBuffer sendMsg = new StringBuffer();

		StringReader strRead = new StringReader(str);

		try {
			while(true){
				byte tmp = (byte)strRead.read();

				// 字符串读取到最后退出循环
				if (tmp == -1) {
					break;
				}

				if (tmp == '^'){
					// 读入^后的两个字符
					char tmpA = (char)strRead.read();
					char tmpB = (char)strRead.read();

					// 将两个hex字符合成一个字符
					int uniteChar = (hexCharToDec(tmpA)<<4) + hexCharToDec(tmpB);
					
					if ( (uniteChar>=0x20 && uniteChar<0x22) || (uniteChar>0x22 && uniteChar<0x5E) || (uniteChar>0x5E && uniteChar<=0x7E) ) {
						// 如果为可显示字符
						sendMsg.append( (char)uniteChar);
					} else if (uniteChar == 0x22) {
						// 将 " 转为 \"
						sendMsg.append("\\\"");
					}
					else if (uniteChar == 0x0D) {
						// 将 0D 转为 \r"
						sendMsg.append("\\r");
					} else if (uniteChar == 0x0A) {
						// 将 0A 转为 \n"
						sendMsg.append("\\n");
					} else {
						// 如果为不可显字符仍然将 ^00 存入
						sendMsg.append('^');
						sendMsg.append(tmpA);
						sendMsg.append(tmpB);
					}
				}
			}
		} catch (IOException e) {
		    e.printStackTrace();
		}

		/*
		 * 将输出信息在屏幕上按一行显示
		 */
		System.out.println("=====================================================");
		System.out.println(sendMsg.toString());
		System.out.println("=====================================================");
		/*
		 * 将输出信息在屏幕上按折行显示
		 */
		String tmpStr = sendMsg.toString();
		int tmpStrLen = tmpStr.length();
		int beginIndex = 0;
		while (true) {
			if (beginIndex >= tmpStrLen) {
				break;
			} else {
				int endIndex = beginIndex + lineLen;
				if (endIndex > tmpStrLen) {
					System.out.println(prefixStr + "( \"" + tmpStr.substring(beginIndex) + "\" );");
				} else {
					System.out.println(prefixStr + "( \"" + tmpStr.substring(beginIndex, endIndex) + "\" );");
				}
				beginIndex = endIndex;
			}
		}
		System.out.println("=====================================================");
	}

}
